package net.xm;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.StringReader;
import java.io.StringWriter;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.TransformerException;

import org.apache.log4j.Logger;
import org.apache.xpath.XPathAPI;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;

import com.sun.org.apache.xml.internal.serialize.OutputFormat;
import com.sun.org.apache.xml.internal.serialize.XMLSerializer;

/**
 * Created by IntelliJ IDEA.
 * Date: 09-Jan-2007
 * Time: 15:33:55
 * XML Utils
 */
public class XmlUtils {
    private static Logger logger =
            Logger.getLogger(XmlUtils.class);
     public static Document createDocumentFromString(String xml)
            throws ApplicationException {

        try {
            DocumentBuilderFactory factory =
                    DocumentBuilderFactory.newInstance();
            DocumentBuilder builder = factory.newDocumentBuilder();
            return builder.parse(new InputSource(new StringReader(xml)));
        } catch (ParserConfigurationException e) {
            logger.error(e.getMessage(), e);
            throw new ApplicationException(e);
        } catch (SAXException e) {
            logger.error(e.getMessage(), e);
            throw new ApplicationException(e);
        } catch (IOException e) {
            logger.error(e.getMessage(), e);
            throw new ApplicationException(e);
        }
    }

    public static NodeList selectNodes(Document document, String xPath)
            throws ApplicationException {
    	NodeList res=null;
        try {
            res=XPathAPI.selectNodeList(document, xPath);
        } catch (TransformerException e) {
            throw new ApplicationException(e);
        }
        return res;
    }

    public static String extractSingleElementValue(Node aNode, String xPath)
               throws ApplicationException {
           try {
               Node node = XPathAPI.selectSingleNode(aNode, xPath);
               if (node != null) {
                   Node textNode = node.getFirstChild();
                   if (textNode != null) {

                       return node.getFirstChild().getNodeValue();
                   } else {
                       return null;
                   }
               } else {
                   return null;
               }
           } catch (TransformerException e) {
               logger.error(e.getMessage(), e);
               throw new ApplicationException(e);
           }
    }

	public static String toString(Document doc) throws ApplicationException{
		String sOut = null;
		try {
			OutputFormat format = new OutputFormat(doc); //Serialize DOM
			StringWriter stringOut = new StringWriter(); //Writer will be a String
			XMLSerializer serial = new XMLSerializer(stringOut, format);
			serial.asDOMSerializer(); // As a DOM Serializer
			serial.serialize(doc.getDocumentElement());
			sOut = stringOut.toString();
		} catch (IOException e) {
			logger.error(e.getMessage(),e);
            throw new ApplicationException(e);
		}
		return sOut;
	}
	
	/**
	 * Read an xml document from a file
	 * @param filename Name of a file containing xml
	 * @param validating If true, validate against a DTD referenced in the file
	 * @return An xml document
	 * @throws ApplicationException 
	 */
	public static Document parseXmlFile(String filename, boolean validating) throws ApplicationException {
        try {
            // Create a builder factory
            DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
            factory.setValidating(validating);
            // Create the builder and parse the file
            Document doc = factory.newDocumentBuilder().parse(new File(filename));
            return doc;
        } 
        catch (SAXException e) {
            logger.error(e.getMessage(),e);
            throw new ApplicationException(e);
        } 
        catch (ParserConfigurationException e) {
        	 logger.error(e.getMessage(),e);
             throw new ApplicationException(e);
        } 
        catch (IOException e) {
        	 logger.error(e.getMessage(),e);
             throw new ApplicationException(e);
        }       
    }
	
	/**
	 * Read an xml document from an InputStream
	 * @param is InputStream
	 * @return An xml document
	 * @throws ApplicationException
	 */
	public static Document readDocumentFromInputStream(InputStream is) throws ApplicationException {
		try {			
		    DocumentBuilderFactory factory =
		            DocumentBuilderFactory.newInstance();
		    factory.setValidating(false);
		    DocumentBuilder builder = factory.newDocumentBuilder();		    
		    return builder.parse(is);
		} catch (ParserConfigurationException e) {
			logger.error(e.getMessage(), e);
		    throw new ApplicationException(e);
		} catch (SAXException e) {
			logger.error(e.getMessage(), e);
		    throw new ApplicationException(e);
		} catch (IOException e) {
			logger.error(e.getMessage(), e);
		    throw new ApplicationException(e);
		}
	}

	public static String extractSingleAttributeValue(Node node, String string) {
		return node.getAttributes().getNamedItem(string).getNodeValue();
	}


}
